using System;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;
using System.Threading;

using Stunt.Nutss;
using Stunt.Nutss.Stunt;

/// <summary>
/// Listen for connections on a STUNT Endpoint and execute the echo protocol (RFC ???).
/// </summary>

namespace EchoServer {

    class EchoServer
    {
        static Semaphore semaphore = new Semaphore(0, 10);
        static LinkedList<Socket> sockets = new LinkedList<Socket>();
        static LinkedList<NutssUri> uris = new LinkedList<NutssUri>();
        static NutssUri i;

        internal class Handler : STUNTEventAdapter
        {

            public override void AcceptHandler(Socket sock, NutssUri remoteAddress)
            {
                lock (EchoServer.semaphore)
                {
                    //sockets.AddLast(sock.socket());
                    sockets.AddLast(sock);
                    uris.AddLast(remoteAddress);
                    EchoServer.semaphore.Release();
                }
            }

            public override void ErrorHandler(Exception e)
            {
                System.Console.Error.WriteLine("An error occurred. If this is unexpected, please run with '-d'\n" + "as the first argument and email the log created in EchoServerLog.txt\n" + "to Saikat Guha <saikat@cs.cornell.edu>. Thanks\n");
                SupportClass.WriteStackTrace(e, Console.Error);
                System.Environment.Exit(1);
            }
        }

        internal class Responder : SupportClass.ThreadClass
        {

            internal System.Net.Sockets.TcpClient s;
            internal System.IO.StreamReader in_Renamed;
            //UPGRADE_ISSUE: Class hierarchy differences between 'java.io.PrintStream' and 'System.IO.StreamWriter' may cause compilation errors. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1186'"
            internal System.IO.StreamWriter out_Renamed;

            internal virtual void close()
            {
                try
                {
                    if (out_Renamed != null)
                        out_Renamed.Close();
                    if (in_Renamed != null)
                        in_Renamed.Close();
                    if (s != null)
                        s.Close();
                }
                catch (System.Exception e)
                {
                }
            }

            internal Responder(System.Net.Sockets.TcpClient s, NutssUri u)
            {
                try
                {

                    //UPGRADE_TODO: The differences in the expected value  of parameters for constructor 'java.io.BufferedReader.BufferedReader'  may cause compilation errors.  "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1092'"
                    //UPGRADE_WARNING: At least one expression was used more than once in the target code. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1181'"
                    in_Renamed = new System.IO.StreamReader(new System.IO.StreamReader(s.GetStream(), System.Text.Encoding.Default).BaseStream, new System.IO.StreamReader(s.GetStream(), System.Text.Encoding.Default).CurrentEncoding);
                    //UPGRADE_ISSUE: Class hierarchy differences between 'java.io.PrintStream' and 'System.IO.StreamWriter' may cause compilation errors. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1186'"
                    out_Renamed = new System.IO.StreamWriter(s.GetStream());
                    out_Renamed.WriteLine("Greetings " + u + ", this is the EchoServer at " + EchoServer.i + ". Now you say something.");
                    System.Console.Out.WriteLine("Accepted " + u);
                }
                catch (System.Exception e)
                {
                    close();
                }
            }

            override public void Run()
            {
                try
                {
                    System.String s;
                    while ((s = in_Renamed.ReadLine()) != null)
                        out_Renamed.WriteLine(s);
                }
                catch (System.Exception e)
                {
                }
                finally
                {
                    close();
                }

            }
        }

        [STAThread]
        static void Main(string[] args){

            try
            {
                i = new NutssUri(args[0]);
            }
            catch (System.IndexOutOfRangeException)
            {
                Console.WriteLine("Usage:\n\t EchoServer you@your.domain.com\n");
                System.Environment.Exit(1);
            }

            try
            {
                STUNTEndpoint sock = new STUNTEndpoint(i);
                sock.Listen(new Handler());
                while (true)
                {
                    //semaphore.acquire();
                    lock (semaphore)
                    {

                        LinkedListNode<Socket> lls = sockets.First;
                        Socket s = lls.Value;
                        sockets.RemoveFirst();
                        //					new Responder(sockets.RemoveFirst(), uris.RemoveFirst()).Start();
                        new Responder(new TcpClient((System.Net.IPEndPoint)s.LocalEndPoint), uris.First.Value).Start();

                    }
                }
            }
            catch (System.Exception e)
            {
                System.Console.Error.WriteLine("An error occurred");
                SupportClass.WriteStackTrace(e, Console.Error);
                Console.ReadLine();
                System.Environment.Exit(1);
            }
        } // end main

    }// end class
} // end namespace